#pragma once

#include "class/hid/hid_device.h"

#if !defined TUD_HID_REPORT_DESC_ABSMOUSE
// This version of arduino-esp32 does not handle absolute mouse natively.
// Let's throw a minimalistic implementation of absmouse driver.
// See: https://github.com/hathach/tinyusb/pull/1363
// Also see: https://github.com/espressif/arduino-esp32/pull/6331

extern "C" {

// Absolute Mouse data struct is a copy of the relative mouse struct
// with int16_t instead of int8_t for X and Y coordinates.
typedef struct TU_ATTR_PACKED {
  uint8_t buttons = 0;
  int16_t x = 0;
  int16_t y = 0;
  int8_t wheel = 0;
  int8_t pan = 0;
} hid_abs_mouse_report_t;

// Absolute Mouse Report Descriptor Template applies those datatype changes too
#define TUD_HID_REPORT_DESC_ABSMOUSE(...)                                                                                                               \
  HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), HID_USAGE(HID_USAGE_DESKTOP_MOUSE), HID_COLLECTION(HID_COLLECTION_APPLICATION), /* Report ID if any */        \
    __VA_ARGS__ HID_USAGE(HID_USAGE_DESKTOP_POINTER), HID_COLLECTION(HID_COLLECTION_PHYSICAL), HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), HID_USAGE_MIN(1), \
    HID_USAGE_MAX(5), HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(1),                                   /* Left, Right, Middle, Backward, Forward buttons */    \
    HID_REPORT_COUNT(5), HID_REPORT_SIZE(1), HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), /* 3 bit padding */                                     \
    HID_REPORT_COUNT(1), HID_REPORT_SIZE(3), HID_INPUT(HID_CONSTANT), HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), /* X, Y absolute position [0, 32767] */   \
    HID_USAGE(HID_USAGE_DESKTOP_X), HID_USAGE(HID_USAGE_DESKTOP_Y), HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x7FFF, 2), HID_REPORT_SIZE(16),           \
    HID_REPORT_COUNT(2), HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), /* Vertical wheel scroll [-127, 127] */                                     \
    HID_USAGE(HID_USAGE_DESKTOP_WHEEL), HID_LOGICAL_MIN(0x81), HID_LOGICAL_MAX(0x7f), HID_REPORT_COUNT(1), HID_REPORT_SIZE(8),                          \
    HID_INPUT(HID_DATA | HID_VARIABLE | HID_RELATIVE), HID_USAGE_PAGE(HID_USAGE_PAGE_CONSUMER), /* Horizontal wheel scroll [-127, 127] */               \
    HID_USAGE_N(HID_USAGE_CONSUMER_AC_PAN, 2), HID_LOGICAL_MIN(0x81), HID_LOGICAL_MAX(0x7f), HID_REPORT_COUNT(1), HID_REPORT_SIZE(8),                   \
    HID_INPUT(HID_DATA | HID_VARIABLE | HID_RELATIVE), HID_COLLECTION_END, HID_COLLECTION_END

static inline bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
  hid_abs_mouse_report_t report = {.buttons = buttons, .x = x, .y = y, .wheel = vertical, .pan = horizontal};
  return tud_hid_n_report(instance, report_id, &report, sizeof(report));
}

static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
  return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
}

}  // end extern "C"

#else
#pragma message "This file is now safe to delete along with its include from USBHIDMouse.h"
#endif
